package com.cq.designPattern.singleton;

/**
 * 懒汉模式
 * 优点：这样的好处是省了一段时间的内存(不创建对象)
 * 缺点：多人同时并发获取对象的话，依然会创建多个对象
 */
public class LazyLoad {
    private static LazyLoad lazyLoad;
    private LazyLoad(){}
    public static LazyLoad getLazyLoad(){
        if (lazyLoad==null){//如果不存在对象就创建对象
            lazyLoad = new LazyLoad();
        }
        return lazyLoad;
    }
}

/**
 * 优化1
 * 缺点：所有请求创建对象都会被加锁，造成时间浪费，没有利用好并发
 */
class LazyLoad1 {
    private static LazyLoad1 lazyLoad1;
    private LazyLoad1(int i){
        System.out.println("编号【"+i+"】创建了对象");
    }
    public static synchronized LazyLoad1 getLazyLoad1(int j){
        if (lazyLoad1==null){//如果不存在对象就创建对象
            lazyLoad1 = new LazyLoad1(j);
        }
        return lazyLoad1;
    }
}
class LazyLoad2 {
    private static LazyLoad2 lazyLoad2;
    private LazyLoad2(int i){
        System.out.println("编号【"+i+"】创建了对象");
    }
    public static LazyLoad2 getLazyLoad2(int j){
        if (lazyLoad2==null){///如果第一个对象未产生，这批人就进入排队。
            synchronized(LazyLoad2.class){
                if (lazyLoad2==null){//创建对象后，其他抢着创建的白排队了
                    lazyLoad2 = new LazyLoad2(j);
                }
            }
        }
        //此处对象产生后，就不再排队
        return lazyLoad2;
    }
}

/**
 * 静态内部类第一次加载的时候并不会初始化实例，只有在getSingleton()的时候，才会
 去创建实例。因此这种方式不仅可以保证线程的安全，也能够保证单例对象的唯一性，同时
 也延迟了单例的实例化，所以这是推荐的使用方式。
 */
class Singleton {

    private static class SingletonHolder {
        private static final Singleton singleton = new Singleton();
    }

    private Singleton(){
    }

    public static Singleton getSingleton(){
        return SingletonHolder.singleton;
    }
}
class  Test{
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            LazyLoad2.getLazyLoad2(i);
        }
    }
}
